# -*- coding: utf-8 -*-
'''
	python 语言相关
'''

import traceback,json,os,logging,re

def readJson(jfile):
	'''
		读取json文件
	'''
	with open(jfile, 'r', encoding='utf-8') as f:
		return json.load(f)

def writeJson(data, jfile, debug=False):		
	'''
		写入json文件
		@param debug 调试写入，文件更易读
	'''
	with open(jfile, 'w', encoding='utf-8') as f:
		if debug:
			f.write(json.dumps(data, indent=4, separators=(',', ': '), ensure_ascii=False))
		else:
			f.write(json.dumps(data, separators=(',', ':'), ensure_ascii=False))

def printTraceback():
	''' 
		打印执行轨迹 
	'''
	traceback.print_exc()

def wildcardMatch(wcs, str):	
	'''
		通配符匹配
	'''
	widx = 0
	sidx = 0
	while True:
		if widx >= len(wcs):
			return sidx >= len(str)
		if wcs[widx] == "?":
			widx += 1
			sidx += 1
		elif wcs[widx] == "*":
			widx += 1
			while sidx < len(str):
				if wildcardMatch(wcs[widx:],str[sidx:]):
					return True
				sidx += 1
			return widx >= len(wcs)
		else:
			if widx>=len(wcs) or sidx>=len(str) or wcs[widx] != str[sidx]:
				return False
			widx += 1
			sidx += 1

def wildcardMatchs(wcslist, str):
	'''
		通配符列表匹配
	'''
	for wcs in wcslist:
		if wildcardMatch(wcs, str):
			return True
	return False

def setDictPath(dicto, path, value):	
	'''
		设置字典路径的值
	'''
	if isinstance(path, str):
		sps = path.split('.')
	else: # list
		sps = path
	for i in range(len(sps) - 1):
		spath = sps[i]
		if spath not in dicto:
			newobj = {}
			dicto[spath] = newobj
			dicto = newobj
		else:
			dicto = dicto[spath]
	dicto[sps[-1]] = value

def getDictPath(dicto, path, default = None):
	'''
		获得字典路径的值
	'''
	if isinstance(path, str):
		sps = path.split('.')
	else: # list
		sps = path
	result = dicto
	for p in sps:
		result = result.get(p)
		if result == None:
			return default
	return result

def removeDictPath(dicto, path):
	'''
		移除字典路径
	'''
	if isinstance(path, str):
		sps = path.split('.')
	else: # list
		sps = path
	if len(sps) > 1:
		dicto = getDictPath(dicto, sps[0:-2])
	if dicto:
		key = sps[-1]
		if key in dicto:
			del dicto[key]

def mergeDict(dmap, smap, force = False):
	'''
		合并Dict
		* Map表合并规则：<br/>
		* 遍历源Map表字段，对比目的Map表对应字段，存在几种情况：<br/>
		* 1、目的Map表中不存在该字段，直接设置为源Map表字段<br/>
		* 2、目的Map表字段和源Map表字段同为数组(Array)，把字段的源Map表数组复制到目的Map表数组中<br/>
		* 3、目的Map表字段和源Map表字段同为对象(Object)，以字段的目的Map表和源Map表为参数再次调用次函数<br/>
		* 4、其他情况，说明存在冲突。警告后，源Map表字段直接覆盖目的Map表字段
	'''
	for (key, svalue) in smap.items():
		dvalue = dmap.get(key)
		if dvalue == None:
			dmap[key] = svalue
		else:
			if isinstance(svalue, list) and isinstance(dvalue, list):
				dvalue.extend(svalue)
			elif isinstance(svalue, dict) and isinstance(dvalue, dict):
				mergeDict(dvalue, svalue, force)
			else:
				if not force:
					logging.error('mergeDict conflict')
				else:
					logging.warn('mergeDict conflict')
					dmap[key] = svalue

def isNumber(s):
	'''
		判断字符串为数值
	'''
	try:
		float(s)
		return True
	except ValueError:
		pass

	import unicodedata
	try:
		unicodedata.numeric(s)
		return True
	except (TypeError, ValueError):
		pass
		
	if len(s) < 2:
		return False

	try:
		d = 0
		if s.startswith('－'):
			s = s[1:]
		for c in s:
			if c == '－': # 全角减号
				return False
				
			if c == '．': # 全角点号
				if d > 0:
					return False
				else:
					d = 1
					continue
			unicodedata.numeric(c)
		return True
	except (TypeError, ValueError):
		pass

	return False

# C转义正则表达式
C_RE_C_ESCAPE_OCT = re.compile(r'\\[0-7]{1,3}')
C_RE_C_ESCAPE_HEX = re.compile(r'\\x[0-9A-Fa-f]+')

# C 转义表
C_C_ESCAPES = (
	("\\" , "\\\\"),
	("\a" , "\\a"),
	("\b" , "\\b"),
	("\f" , "\\f"),
	("\n" , "\\n"),
	("\r" , "\\r"),
	("\t" , "\\t"),
	("\v" , "\\v"),
	("\'" , "\\\'"),
	("\"" , "\\\""),
	("?"  , "\\?"),
)

def loadCString(cstr):
	'''
		加载C字符串
	'''
	def _rep_oct(str):
		return chr(int(str.group()[1:],8))
	def _rep_hex(str):
		return chr(int(str.group()[2:],16))
	cstr = C_RE_C_ESCAPE_OCT.sub(_rep_oct, cstr)
	cstr = C_RE_C_ESCAPE_HEX.sub(_rep_hex, cstr)
	for escape in C_C_ESCAPES:
		cstr = cstr.replace(escape[1],escape[0])
	return cstr
